package com.dtflys.easyel.ast;

import com.dtflys.easyel.runtime.EasyElDate;
import com.dtflys.easyel.runtime.EasyElRange;
import com.dtflys.easyel.runtime.EasyElRuntimeContext;
import com.dtflys.easyel.runtime.EasyElTimeDuration;
import com.dtflys.easyel.utils.TypeHelper;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author gongjun[jun.gong@thebeastshop.com]
 * @since v1.0.0
 */
public class ASTType extends ASTExpression {

    public final static ASTType UNDEFINED = new ASTType("Undefined");
    static {
        UNDEFINED.setUndefined(true);
    }

    public final static ASTType TYPE = new ASTType("Type", Type.class);

    public final static ASTType OBJECT = new ASTType("Object", Object.class);

    public final static ASTType BOOLEAN = new ASTType("Boolean", Boolean.class);

    public final static ASTType INTEGER = new ASTType("Integer", Integer.class);

    public final static ASTType LONG = new ASTType("Long", Long.class);

    public final static ASTType FLOAT = new ASTType("Float", Float.class);

    public final static ASTType DOUBLE = new ASTType("Double", Double.class);

    public final static ASTType NUMERIC = new ASTType("Numeric", BigDecimal.class);

    public final static ASTType STRING = new ASTType("String", String.class);

    public final static ASTType RANGE = new ASTType("Range", EasyElRange.class);

    public final static ASTType LIST = new ASTType("List", List.class);

    public final static ASTType MAP = new ASTType("Map", Map.class);

    public final static ASTType MAP_ENTRY = new ASTType("MapEntry", Map.Entry.class);

    public final static ASTType DATE = new ASTType("Date", EasyElDate.class);

    public final static ASTType TIME_DURATION = new ASTType("Date", EasyElTimeDuration.class);


    public static ASTType fromJavaClass(Class cls) {
        if (TypeHelper.isJavaInteger(cls)) {
            return INTEGER;
        }
        if (TypeHelper.isJavaLong(cls)) {
            return LONG;
        }
        if (TypeHelper.isJavaFloat(cls)) {
            return FLOAT;
        }
        if (TypeHelper.isJavaDouble(cls)) {
            return DOUBLE;
        }
        if (TypeHelper.isNumeric(cls)) {
            return NUMERIC;
        }
        if (TypeHelper.isString(cls)) {
            return STRING;
        }
        if (TypeHelper.isBoolean(cls)) {
            return BOOLEAN;
        }
        if (Object.class == cls) {
            return OBJECT;
        }
        return new ASTType(cls.getSimpleName(), cls);
    }


    private final String importedName;

    private Class clazz;

    private boolean isUndefined = false;


    public ASTType(String importedName, Class clazz) {
        super(TYPE);
        this.importedName = importedName;
        this.clazz = clazz;
    }

    public ASTType(String importedName) {
        super(TYPE);
        this.importedName = importedName;
    }

    public String getImportedName() {
        return importedName;
    }

    public Class getClazz() {
        return clazz;
    }

    public boolean isUndefined() {
        return isUndefined;
    }

    public void setUndefined(boolean undefined) {
        isUndefined = undefined;
    }

    @Override
    public String visit(EasyElRuntimeContext context, ASTVisitor visitor) {
        visitor.visitType(context, this);
        return null;
    }

    @Override
    public String getText() {
        if (clazz != null) {
            return clazz.getName();
        }
        return getImportedName();
    }

    @Override
    public String toString() {
        return getText();
    }
}
